#include "UvcCamera.h"
#include "PluginManager.h"
#include "Log.h"
// 默认设置debug模式为false
bool DEBUG_ENABLE = false;
/**
 * debug开关
 * @param env
 * @param info
 * @return
 */
static napi_value nativeEnableDebug(napi_env env, napi_callback_info info) {
    napi_value args[1] = {0};
    size_t argc = 1;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int debugStatus;
    if (!napiUtils::loadNapiInt(env, args[0], &debugStatus)) {
        return napiUtils::createIntNapi(env, 0);
    }
    DEBUG_ENABLE = debugStatus == 1;
    LOG_D("当前的debug状态:%{public}s", DEBUG_ENABLE ? "打开" : "关闭");
    return napiUtils::createIntNapi(env, 1);
}
// 初始化配置方法
static napi_value nativeCreate(napi_env env, napi_callback_info info) {
    LOG_D("HomeNavigation native nativeCreate");
    return napiUtils::createLongNapi(env, reinterpret_cast<int64_t>(new UvcCamera()));
}

static napi_value nativeDestroy(napi_env env, napi_callback_info info) {
    LOG_D("HomeNavigation native nativeDestroy");
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        LOG_D("HomeNavigation native nativeDestroy--load failed");
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    LOG_D("HomeNavigation native nativeDestroy--cameraId:%{public}ld", cameraId);
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        delete (camera);
        camera = nullptr;
    }
    return napiUtils::createIntNapi(env, 1);
}


static napi_value nativeConnect(napi_env env, napi_callback_info info) {
    napi_value args[5] = {0};
    size_t argc = 5;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    int32_t vId;
    int32_t pId;
    int32_t busNum;
    int32_t devAddress;
    if (!napiUtils::loadNapiInt(env, args[1], &vId) || !napiUtils::loadNapiInt(env, args[1], &vId) ||
        !napiUtils::loadNapiInt(env, args[3], &busNum) || !napiUtils::loadNapiInt(env, args[4], &devAddress)) {
        return napiUtils::createIntNapi(env, 0);
    }
    if (camera) {
        int ret = camera->connect(vId, pId, busNum, devAddress);
        return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeConnectFd(napi_env env, napi_callback_info info) {
    napi_value args[4] = {0};
    size_t argc = 4;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    int32_t fd;
    int32_t busNum;
    int32_t devAddress;
    if (!napiUtils::loadNapiInt(env, args[1], &fd) || !napiUtils::loadNapiInt(env, args[2], &busNum) ||
        !napiUtils::loadNapiInt(env, args[3], &devAddress)) {
        return napiUtils::createIntNapi(env, 0);
    }
    int ret;
    if (camera) {
        ret = camera->connectFd(fd, busNum, devAddress);
    } else {
        ret = UVC_ERROR_NO_DEVICE;
    }
    return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
}

static napi_value nativeDisConnect(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        int ret = camera->disConnect();
        return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeStartPreview(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        int ret = camera->startPreview();
        return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeStopPreview(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        int ret = camera->stopPreview();
        return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeGetPreviewSize(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        int width = camera->getPreviewWidth();
        int height = camera->getPreviewHeight();
        LOG_D("当前获取到的值:%d-%d", width, height);
        if (width == -1 || height == -1) {
            return nullptr;
        }
        napi_value widthValue = napiUtils::createIntNapi(env, width);
        napi_value heightValue = napiUtils::createIntNapi(env, height);
        napi_value formatValue = napiUtils::createIntNapi(env, camera->loadCurrentFormat());
        if (widthValue == nullptr || heightValue == nullptr || formatValue == nullptr) {
            return nullptr;
        }
        napi_value arrayValue = napiUtils::createArrayNapi(env, 3);
        if (arrayValue == nullptr) {
            return nullptr;
        }
        napi_set_element(env, arrayValue, 0, widthValue);
        napi_set_element(env, arrayValue, 1, heightValue);
        napi_set_element(env, arrayValue, 2, formatValue);
        return arrayValue;
    }
    return nullptr;
}
static napi_value nativeSetPreviewSize(napi_env env, napi_callback_info info) {
    napi_value args[5] = {0};
    size_t argc = 5;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);

    int32_t width;
    int32_t height;
    int32_t format;
    if (!napiUtils::loadNapiInt(env, args[1], &width) || !napiUtils::loadNapiInt(env, args[2], &height) ||
        !napiUtils::loadNapiInt(env, args[3], &format)) {
        return napiUtils::createIntNapi(env, 0);
    }
    if (camera) {
        int ret = camera->setPreviewSize(width, height, format);
        return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeGetSupportPreviewSizes(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        char *ret = camera->getSupportedPreviewSizes();
        if (ret) {
            return napiUtils::createStringNapi(env, ret);
        }
        return nullptr;
    }
    return nullptr;
}

static napi_value nativeSetDisplaySurface(napi_env env, napi_callback_info info) {
    napi_value args[2] = {0};
    size_t argc = 2;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    char *surfaceId = napiUtils::loadNapiString(env, args[1]);
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId) || !surfaceId) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        int ret = camera->setDisplaySurface(surfaceId);
        return napiUtils::createIntNapi(env, ret == UVC_SUCCESS ? 1 : 0);
    }
    free_napi(surfaceId);
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeSetPreviewListener(napi_env env, napi_callback_info info) {
    napi_value args[3] = {0};
    size_t argc = 3;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    int32_t mode;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId) || !napiUtils::loadNapiInt(env, args[2], &mode)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        camera->setPreviewDataListener(env, args[1], mode);
        return napiUtils::createIntNapi(env, 1);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeGetParameterIntValue(napi_env env, napi_callback_info info) {
    napi_value args[2] = {0};
    size_t argc = 2;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return nullptr;
    }
    int type;
    if (!napiUtils::loadNapiInt(env, args[1], &type)) {
        return nullptr;
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        int value = camera->getParameterIntValue(type);
        return value == -9999 ? nullptr : napiUtils::createIntNapi(env, value);
    }
    return nullptr;
}

static napi_value nativeSetParameterIntValue(napi_env env, napi_callback_info info) {
    napi_value args[3] = {0};
    size_t argc = 3;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    int type;
    int value;
    if (!napiUtils::loadNapiInt(env, args[1], &type) || !napiUtils::loadNapiInt(env, args[2], &value)) {
        return napiUtils::createIntNapi(env, 0);
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        bool ret = camera->setParameterIntValue(type, value);
        return napiUtils::createIntNapi(env, ret ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeGetSupportedParameters(napi_env env, napi_callback_info info) {
    napi_value args[2] = {0};
    size_t argc = 2;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    int64_t cameraId;
    int type;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId) || !napiUtils::loadNapiInt(env, args[1], &type)) {
        return nullptr;
    }
    UvcCamera *camera = reinterpret_cast<UvcCamera *>(cameraId);
    if (camera) {
        std::pair<int, int> range = camera->getParameterRange(type);
        if (range.first == -9999 && range.second == -9999) {
            return nullptr;
        }
        napi_value start = napiUtils::createIntNapi(env, range.first);
        napi_value end = napiUtils::createIntNapi(env, range.second);
        if (start == nullptr || end == nullptr) {
            return nullptr;
        }
        napi_value arrayValue = napiUtils::createArrayNapi(env, 2);
        if (arrayValue == nullptr) {
            return nullptr;
        }
        napi_set_element(env, arrayValue, 0, start);
        napi_set_element(env, arrayValue, 1, end);
        return arrayValue;
    }
    return nullptr;
}

EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        // 方法描述列表
        {"nativeEnableDebug", nullptr, nativeEnableDebug, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeCreate", nullptr, nativeCreate, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeDestroy", nullptr, nativeDestroy, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeConnect", nullptr, nativeConnect, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeConnectFd", nullptr, nativeConnectFd, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeDisConnect", nullptr, nativeDisConnect, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeStartPreview", nullptr, nativeStartPreview, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeStopPreview", nullptr, nativeStopPreview, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeSetDisplaySurface", nullptr, nativeSetDisplaySurface, nullptr, nullptr, nullptr, napi_default, nullptr},

        {"nativeGetSupportPreviewSizes", nullptr, nativeGetSupportPreviewSizes, nullptr, nullptr, nullptr, napi_default,
         nullptr},
        {"nativeGetPreviewSize", nullptr, nativeGetPreviewSize, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeSetPreviewSize", nullptr, nativeSetPreviewSize, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeGetParameterIntValue", nullptr, nativeGetParameterIntValue, nullptr, nullptr, nullptr, napi_default,
         nullptr},
        {"nativeSetParameterIntValue", nullptr, nativeSetParameterIntValue, nullptr, nullptr, nullptr, napi_default,
         nullptr},
        {"nativeGetSupportedParameters", nullptr, nativeGetSupportedParameters, nullptr, nullptr, nullptr, napi_default,
         nullptr},
        {"nativeSetPreviewListener", nullptr, nativeSetPreviewListener, nullptr, nullptr, nullptr, napi_default,
         nullptr},
    };
    LOG_D("HomeNavigation native Init");
    napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    LOG_D("HomeNavigation native status:%{public}d", status == napi_ok);
    if (status != napi_ok) {
        return nullptr;
    }
    //    开始读取传入的surface数据
    PluginManager::GetInstance()->Export(env, exports);
    return exports;
}
EXTERN_C_END


// 模块配置
static napi_module uvc_cameraModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "uvc_camera",
    .nm_priv = ((void *)0),
    .reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterUvc_cameraModule(void) {
    napi_module_register(&uvc_cameraModule); // 注册模块
}
